#ifndef GX_THREADS_H
#define GX_THREADS_H

#include "Basic/GxLibBasic.h"
#include <intrin.h>
#include <stdio.h>

namespace GxWinSystem
{
namespace Threading
{
	using namespace GxLibBasic;

	typedef Event<> gxThreadProc;
	typedef Event<Object *> gxThreadParameterizedProc;
	class gxThread;

	class SpinLock
	{
	private:
		volatile long lock;
	public:
		SpinLock()
		{
			lock = 0;
		}
		inline bool TryLock()
		{
			return (_InterlockedExchange(&lock, 1) == 0);
		}
		inline void Lock()
		{
			while (_InterlockedExchange(&lock, 1) != 0);
		}
		inline void Unlock()
		{
			_InterlockedExchange(&lock, 0);
		}
	};

	class gxThreadParam
	{
	public:
		gxThread * thread;
		Object * threadParam;
	};
	class gxThread : public Object
	{
		friend unsigned int __stdcall ThreadProc(void * param);
	private:
		 gxThreadParam internalParam;
	public:
		enum gxThreadPriority
		{
			gxtpNormal,
			gxtpAboveNormal,
			gxtpHighest,
			gxtpCritical,
			gxtpBelowNormal,
			gxtpLowest,
			gxtpIdle
		};
	private:
		HANDLE threadHandle;
		RefPtr<gxThreadProc> threadProc;
		RefPtr<gxThreadParameterizedProc> paramedThreadProc;
	public:
		gxThread (gxThreadProc * p);
		gxThread (gxThreadParameterizedProc * p, Object * param);
		~gxThread();
		bool HasParameter();
		void Start();
		void Suspend();
		void SetPriority(gxThreadPriority p);
		gxThreadPriority GetPriority();
		void Terminate();
		HANDLE GetHandle();
	};

	class gxLock : public Object
	{
	private:
		CRITICAL_SECTION handle;
	public:
		gxLock();
		~gxLock();
		void Lock();
		bool TryLock();
		void Unlock();
	};

#define GX_LOCK(lock) for(lock->Lock(); false; lock->Unlock())
}
}

#endif